package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.order.interceptor.UserInfoInterceptor;
import com.atguigu.gmall.wms.vo.StockLockedVo;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping
public class SecondKillController {
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;
    //1、用户点击秒杀
    @GetMapping("secKill/{skuId}")
    @ResponseBody
    public ResponseVo secKill(@PathVariable("skuId")String skuId) throws InterruptedException {
        String userId = UserInfoInterceptor.getUserInfo().getUserId();
        if(StringUtils.isEmpty(userId)){
            return ResponseVo.fail("请登录");
        }
        //1、判断库存是否足够
        String stockStr = redisTemplate.opsForValue().get("sec:kill:" + skuId);
        if(StringUtils.isEmpty(stockStr)){
            return ResponseVo.fail("秒杀未开始");
        }
        //2、获取分布式信号量：资源数量
        RSemaphore semaphore = redissonClient.getSemaphore("sec:semaphore:" + skuId);
        //3、超时尝试获取信号量资源：如果有异常 代表未初始化库存 秒杀未开始
        //如果获取成功返回true  失败返回false
        boolean b = semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS);
//        semaphore.release(); 释放获取的资源 秒杀成功不释放 秒杀失败或者不支付释放资源
        if(!b){
            //4、获取失败：秒杀失败
            return ResponseVo.fail("秒杀已结束");
        }
        //5、获取成功：秒杀成功
        //6、生成订单编号+userId+skuId 发送秒杀成功的mq消息
        String orderToken = IdWorker.getIdStr();
        Map<String,Object> map = new HashMap();
        map.put("userId",userId);
        map.put("skuId",skuId);
        map.put("orderToken",orderToken);
        rabbitTemplate.convertAndSend("sec.exchange" , "sec.kill.success"
            ,map);
        //7、初始化闭锁： 避免支付页面回显订单详情时 异步创建订单还未执行结束
        redissonClient.getCountDownLatch("sec:cdl:"+orderToken).trySetCount(1);
        //8、返回秒杀成功：前端可以跳转到支付页面回显订单详情
        return ResponseVo.ok(orderToken);
    }
    @Autowired
    RedissonClient redissonClient;
    //2、用户秒杀成功后 回显订单并支付接口
    @GetMapping("secPay/{orderToken}")
    public String secPay(@PathVariable("orderToken")String orderToken){
        try {
            //获取闭锁
            RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("sec:cdl:" + orderToken);
            countDownLatch.await();//阻塞等待订单创建完毕
            //根据orderToken查询订单详情 设置到域中跳转到页面回显
            System.out.println("订单查询成功:"+ orderToken);

            return "pay";
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "error";
        }
    }

}
